package com.dcy.order.center.service.impl;

import com.dcy.account.api.api.AccountApi;
import com.dcy.account.api.dto.AccountDTO;
import com.dcy.inventory.api.api.InventoryApi;
import com.dcy.inventory.api.dto.InventoryDTO;
import com.dcy.order.api.enums.OrderStatusEnum;
import com.dcy.order.api.model.Order;
import com.dcy.order.center.mapper.OrderMapper;
import com.dcy.order.center.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.hmily.annotation.HmilyTCC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Author：dcy
 * @Description:
 * @Date: 2021/11/16 15:02
 */
@Slf4j
@Service
public class PaymentServiceImpl implements PaymentService {

    @DubboReference(version = "1.0.0", check = false, url = "dubbo://192.168.0.38:20881")
    private AccountApi accountApi;

    @DubboReference(version = "1.0.0", check = false, url = "dubbo://192.168.0.38:20882")
    private InventoryApi inventoryApi;
    @Autowired
    private OrderMapper orderMapper;

    /**
     * 订单支付
     *
     * @param order 订单实体
     */
    @Override
    @HmilyTCC(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
    public void makePayment(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAYING);
        //做库存和资金账户的检验工作 这里只是demo 。。。
       /* final AccountDO accountDO = accountService.findByUserId(order.getUserId());
        if (accountDO.getBalance().compareTo(order.getTotalAmount()) <= 0) {
            throw new HmilyRuntimeException("余额不足！");
        }
        final InventoryDO inventory = inventoryService.findByProductId(order.getProductId());

        if (inventory.getTotalInventory() < order.getCount()) {
            throw new HmilyRuntimeException("库存不足！");
        }*/
        //扣除用户余额
        accountApi.payment(buildAccountDTO(order));
        //进入扣减库存操作
        inventoryApi.decrease(buildInventoryDTO(order));
    }

    @Override
    @HmilyTCC(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
    public String mockPaymentInventoryWithTryException(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAYING);
        //扣除用户余额
        accountApi.payment(buildAccountDTO(order));
        inventoryApi.mockWithTryException(buildInventoryDTO(order));
        return "success";
    }

    @Override
    @HmilyTCC(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
    public String mockPaymentInventoryWithTryTimeout(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAYING);
        //扣除用户余额
        accountApi.payment(buildAccountDTO(order));
        inventoryApi.mockWithTryTimeout(buildInventoryDTO(order));
        return "success";
    }

    @Override
    @HmilyTCC(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
    public String mockPaymentAccountWithTryException(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAYING);
        accountApi.mockTryPaymentException(buildAccountDTO(order));
        return "success";
    }

    public void confirmOrderStatus(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAY_SUCCESS);
        log.info("=========进行订单confirm操作完成================");
    }

    public void cancelOrderStatus(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAY_FAIL);
        log.info("=========进行订单cancel操作完成================");
    }

    private void updateOrderStatus(Order order, OrderStatusEnum orderStatus) {
        order.setStatus(orderStatus.getCode());
        orderMapper.updateById(order);
        log.info("updateOrderStatus {} ", order);
    }

    private AccountDTO buildAccountDTO(Order order) {
        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setAmount(order.getTotalAmount());
        accountDTO.setUserId(order.getUserId());
        return accountDTO;
    }

    private InventoryDTO buildInventoryDTO(Order order) {
        InventoryDTO inventoryDTO = new InventoryDTO();
        inventoryDTO.setCount(order.getCount());
        inventoryDTO.setProductId(order.getProductId());
        return inventoryDTO;
    }
}
